package com.gisquest.cloud.service.impl;

import com.alibaba.fastjson.JSON;
import com.gisquest.cloud.common.cache.RedisService;
import com.gisquest.cloud.common.exception.BizException;
import com.gisquest.cloud.common.utils.DateUtil;
import com.gisquest.cloud.entity.po.BizLogEntity;
import com.gisquest.cloud.entity.po.Stu;
import com.gisquest.cloud.entity.po.SysLogEntity;
import com.gisquest.cloud.entity.vo.PageVo;
import com.gisquest.cloud.entity.vo.RequestEntity;
import com.gisquest.cloud.entity.vo.RestResult;
import com.gisquest.cloud.entity.vo.SysLogVO;
import com.gisquest.cloud.service.EsService;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import static org.elasticsearch.index.query.QueryBuilders.matchQuery;

@Service
public class EsServiceImpl implements EsService {

    @Value("${rs.biz.key}")
    private String bizLogKey;

    @Value("${rs.sys.key}")
    private String sysLogKey;

    @Autowired
    ElasticsearchTemplate esTemplate;

    @Autowired
    RedisService redisService;


    @Override
    public RestResult<?> saveBizLogToEs(BizLogEntity bizLogEntity) {
        IndexQuery build = new IndexQueryBuilder().withObject(bizLogEntity).build();
        return new RestResult<>().makeSuccessResult(esTemplate.index(build));
    }

    @Override
    public RestResult<?> getBizLogFromEs(RequestEntity requestEntity, PageVo pageVo) {

        //构建分页参数
        Pageable pageable = PageRequest.of(0, 10);
        //构建字段排序
        SortBuilder sortBuilder = new FieldSortBuilder("requestStartTime");
        //排序方式
        sortBuilder.order(SortOrder.DESC);
        //构建原生基本查询


        SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchQuery("description", "am"))
                //分页
                .withPageable(pageable)
                //排序
                .withSort(sortBuilder)
                .build();


        AggregatedPage<Stu> sous = esTemplate.queryForPage(query, Stu.class);
        List<Stu> content = sous.getContent();


        return new RestResult().makeSuccessResult(content);

    }

    @Override
    public RestResult<?> saveSysLogToEs(SysLogVO sysLogVO) {
        SysLogEntity sysLogEntity = new SysLogEntity();
        BeanUtils.copyProperties(sysLogVO, sysLogEntity);
        IndexQuery build = new IndexQueryBuilder().withObject(sysLogEntity).build();
        return new RestResult<>().makeSuccessResult(esTemplate.index(build));
    }

    @Override
    public RestResult<?> getSysLogFromEs(SysLogVO sysLogVO, PageVo pageVo) {
        return null;
    }

    @Override
    public RestResult<?> saveSysLogToRs(SysLogVO sysLogVO) {
        String jsonStr = getSysLogJsonStr(sysLogVO);
        //redis配置的类型指定为list,推荐使用rpush(channel推荐使用publish)
        redisService.rpush(sysLogKey, jsonStr);
        return new RestResult<>().makeSuccessResult();
    }

    @Override
    public RestResult<?> saveBizLogToRs(BizLogEntity bizLogEntity) {
        String jsonStr = getBizLogJsonStr(bizLogEntity);
        //redis配置的类型指定为list,推荐使用rpush(channel推荐使用publish)
        redisService.rpush(bizLogKey, jsonStr);
        return new RestResult<>().makeSuccessResult();
    }


    /**
     * 通过传过来的对象获取存储对象的json字符串(业务日志)
     *
     * @param bizLogEntity
     * @return
     */
    public String getBizLogJsonStr(BizLogEntity bizLogEntity) {
        if (StringUtils.isEmpty(bizLogEntity.getAppId())) {
            throw new BizException("appId不能为空");
        }
        if (StringUtils.isEmpty(bizLogEntity.getUserId()) || StringUtils.isEmpty(bizLogEntity.getUserName())) {
            throw new BizException("userId和userName均不能为空");
        }
        if (StringUtils.isEmpty(bizLogEntity.getYwh()) && StringUtils.isEmpty(bizLogEntity.getOptId())) {
            throw new BizException("业务标识和操作标识不能同时为空");
        }
        if (StringUtils.isEmpty(bizLogEntity.getRequestId())) {
            throw new BizException("请传入请求标识");
        }
        if (StringUtils.isEmpty(bizLogEntity.getRequestUrl())) {
            throw new BizException("请传入请求路径");
        }
        bizLogEntity.setId(UUID.randomUUID().toString().replace("-", ""));
        bizLogEntity.setRequestTime(new Date());
        String jsonStr = JSON.toJSONString(bizLogEntity);
        return jsonStr;
    }

    /**
     * 通过传过来的对象获取存储对象的json字符串(系统日志)
     *
     * @param sysLogVO
     * @return
     */
    public String getSysLogJsonStr(SysLogVO sysLogVO) {
        if (StringUtils.isEmpty(sysLogVO.getRequestId())) {
            throw new BizException("requestId不能为空");
        }
        if (StringUtils.isEmpty(sysLogVO.getMsg())) {
            throw new BizException("日志信息不能为空");
        }
        SysLogEntity sysLogEntity = new SysLogEntity();
        if (StringUtils.isEmpty(sysLogVO.getCreateTime())) {
            //默认为当前时间
            sysLogEntity.setCreateTime(new Date());
        } else {
            sysLogEntity.setCreateTime(DateUtil.getDateFromStr(sysLogVO.getCreateTime()));
        }
        sysLogEntity.setClassName(sysLogVO.getClassName());
        sysLogEntity.setLevel(sysLogVO.getLevel());
        sysLogEntity.setMsg(sysLogVO.getMsg());
        sysLogEntity.setRequestId(sysLogVO.getRequestId());
        String jsonStr = JSON.toJSONString(sysLogEntity);
        return jsonStr;
    }

}
